package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.constant.MqConstant;
import cn.com.dcsgo.constant.PhoneConstant;
import cn.com.dcsgo.dto.BindPhoneDTO;
import cn.com.dcsgo.dto.MemberInfoDTO;
import cn.com.dcsgo.dto.MemberUpdateDTO;
import cn.com.dcsgo.dto.SendVerificationCodeDTO;
import cn.com.dcsgo.exception.BusinessException;
import cn.com.dcsgo.model.SmsModel;
import cn.com.dcsgo.util.VerificationCodeGenerator;
import cn.com.dcsgo.utils.AuthUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.com.dcsgo.domain.Member;
import cn.com.dcsgo.service.MemberService;
import cn.com.dcsgo.mapper.MemberMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.Set;

/**
 * 针对表【member(用户表)】的数据库操作Service实现
 *
 * @author Dcsgo
 * @since 2025-10-30 15:57:19
 */
@Slf4j
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member>
        implements MemberService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    private static final CopyOptions ignoreNullValueCopyOptions = CopyOptions.create().setIgnoreNullValue(true);

    @Override
    public boolean update(MemberUpdateDTO memberUpdateDTO) {
        Member updateData = new Member();
        BeanUtil.copyProperties(memberUpdateDTO, updateData);
        updateData.setId(AuthUtil.getUserId());
        updateData.setOpenId(AuthUtil.getOpenid());
        String nickNameEncode;
        nickNameEncode = URLEncoder.encode(updateData.getNickName(), StandardCharsets.UTF_8);
        updateData.setNickName(nickNameEncode);
        return updateById(updateData);
    }

    @Override
    public List<MemberInfoDTO> findMemberNickNameAndPicByOpenIds(Set<String> openIds) {
        List<Member> memberList = list(
                new LambdaQueryWrapper<Member>()
                        .select(Member::getOpenId, Member::getNickName, Member::getPic)
                        .in(Member::getOpenId, openIds)
        );

        return memberList.stream().map(member -> {
            MemberInfoDTO memberInfoDTO = new MemberInfoDTO();
            BeanUtil.copyProperties(member, memberInfoDTO, ignoreNullValueCopyOptions);
            return memberInfoDTO;
        }).toList();
    }

    @Override
    public void sendPhoneCode(SendVerificationCodeDTO sendVerificationCodeDTO) {
        String phone = sendVerificationCodeDTO.getPhonenum();
        Boolean flag = stringRedisTemplate.opsForValue()
                .setIfAbsent(PhoneConstant.PHONE_CONTROL_PREFIX + phone, "", Duration.ofSeconds(60));
        if (Boolean.FALSE.equals(flag)) {
            throw new BusinessException("请在短信发送1分钟后再试");
        }
        String code = VerificationCodeGenerator.getSimpleCode();
        stringRedisTemplate.opsForValue()
                .set(PhoneConstant.PHONE_CODE_PREFIX + phone, code, Duration.ofMinutes(3));
        // 放发短信的消息到mq中
        SmsModel smsModel = new SmsModel();
        smsModel.setOpenId(AuthUtil.getOpenid());
        smsModel.setPhoneNumber(phone);
        smsModel.setSignName("速通互联验证服务");
        smsModel.setTemplateCode("100004");
        JSONObject templateParamJson = new JSONObject();
        templateParamJson.put("code", code);
        templateParamJson.put("min", 3);
        smsModel.setTemplateParam(templateParamJson.toJSONString());
        SendResult sendResult = rocketMQTemplate.syncSend(MqConstant.SMS_TOPIC, JSON.toJSONString(smsModel));
        log.info("发送绑定手机号验证码，手机号为：{}，验证码为：{}，mq接收结果为：{}", phone, code, sendResult.getSendStatus());
    }

    @Override
    public boolean bindPhone(BindPhoneDTO bindPhoneDTO) {
        String phone = bindPhoneDTO.getPhonenum();
        String code = bindPhoneDTO.getCode();
        String realCode = stringRedisTemplate.opsForValue().get(PhoneConstant.PHONE_CODE_PREFIX + phone);
        if (realCode == null) {
            throw new BusinessException("验证码已失效，请重新获取");
        }
        if (!code.equals(realCode)) {
            throw new BusinessException("验证码错误");
        }
        // 验证通过 删除验证码
        stringRedisTemplate.delete(PhoneConstant.PHONE_CODE_PREFIX + phone);
        // 更新用户信息中的电话号码
        Member member = new Member();
        member.setId(AuthUtil.getUserId());
        member.setUserMobile(phone);
        return updateById(member);
    }
}




